/*
    Dominate 3D - A cube-based game of life

    Copyright (C) 2007, Craig H. Miller (kidmosey@gmail.com)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef _MSC_VER
#include <windows.h>
#endif

#include <GL/gl.h>
#include <GL/glu.h>

void glEnable2D()
{
   int vPort[4];

   glGetIntegerv(GL_VIEWPORT, vPort);

   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   glLoadIdentity();

   glOrtho(vPort[0], vPort[0]+vPort[2], vPort[1], vPort[1]+vPort[3], -1, 1);
   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
   glLoadIdentity();
   glTranslatef(0.375, 0.375, 0.0);

   glPushAttrib(GL_DEPTH_BUFFER_BIT);
   glDisable(GL_DEPTH_TEST);
}

void glDisable2D()
{
   glPopAttrib();
   glMatrixMode(GL_PROJECTION);
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);
   glPopMatrix();
}

int glGetSelection(int mouseX, int mouseY, void (*RenderFunc)())
{
    if (!RenderFunc) return 0;

    // Initialize the selection buffer
    GLuint	buffer[512];
    GLint	hits;
    glSelectBuffer(sizeof(buffer)/sizeof(*buffer), buffer);

    // retrieve viewport settings
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);

    // Init selection mode
    glRenderMode(GL_SELECT);

    // grab the current projection matrix
    GLfloat matProj[16];
    glGetFloatv(GL_PROJECTION_MATRIX, matProj);

    // Setup the projection matrix
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();

    // narrow the projection matrix to a small section of the screen at the mouse.
    gluPickMatrix((GLdouble) mouseX, (GLdouble) (viewport[3]-mouseY), 1.0f, 1.0f, viewport);

    // Reapply the projection matrix
    glMultMatrixf(matProj);

    // Render the objects
    glMatrixMode(GL_MODELVIEW);
    RenderFunc();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    hits=glRenderMode(GL_RENDER);

    if (hits > 0)
    {
        int	choose = buffer[3];									// Make Our Selection The First Object
        int depth = buffer[1];									// Store How Far Away It Is

        for (int loop = 1; loop < hits; loop++)					// Loop Through All The Detected Hits
        {
            // If This Object Is Closer To Us Than The One We Have Selected
            if (buffer[loop*4+1] < GLuint(depth))
            {
                choose = buffer[loop*4+3];						// Select The Closer Object
                depth = buffer[loop*4+1];						// Store How Far Away It Is
            }
        }

        return choose;
    }

    return 0;
}
